
/*
 * @features: 画线组件
 * @description: 说明
 * @Date: 2020-10-14 20:55:13
 * @Author: judu233(769471424@qq.com)
 * @LastEditTime: 2020-10-25 15:41:08
 * @LastEditors: judu233
 */

import { I_LinePoint } from "./IMapType";

const { ccclass, property, disallowMultiple, requireComponent, menu } = cc._decorator;



/**  
    * @Title : 画线
    * @Description : 根据开始和结束的位置画出线条--可控动画
 **/
@ccclass
@disallowMultiple
@requireComponent(cc.Graphics)
@menu(`画线组件`)
export default class LineDraw extends cc.Component {

    /**是否正在绘制 */
    private isDrawing = false;

    /**等待绘制map */
    private waitDrawMap: Map<string, I_LinePoint> = new Map();
    /**等待绘制列表 */
    private waitDrawList: string[] = [];

    onstart() {
        // this.drawLine({
        //     startPos: cc.v3(0, 500, 0),
        //     endPos: cc.v3(300, 200, 0),
        //     drawInterval: 0.05,
        //     step: 10,
        // });
    }

    /**
     *画线
     * @param drawInfo 画线信息
     */
    public drawLine(drawInfo: I_LinePoint) {
        if (this.checkIsDrawIng(drawInfo)) return;

        //赋予默认值
        let warn = (name) => console.warn(`【画线】属性：${name}没有赋值`);
        let graphics = this.node.getComponent(cc.Graphics);
        let { startPos, endPos, drawInterval, step } = drawInfo;

        if (is.undefined(startPos) || is.undefined(endPos)) {
            warn(`开始/结束位置`);
            return;
        }
        drawInterval = is.not.undefined(drawInterval) ? drawInterval : (warn(`绘制间隔时间`), 0.1);
        step = is.not.undefined(step) ? step : (warn(`步长距离`), 10);

        //移动到开始位置
        graphics.moveTo(startPos.x, startPos.y);

        //基本参数
        let x1 = startPos.x, x2 = endPos.x, y1 = startPos.y, y2 = endPos.y;
        let compare = (a: number, b: number) => a < b ? 1 : -1;
        let k = (y2 - y1) / (x2 - x1)   //斜率k     正 负 0
        let b = y1 - k * x1           //常数b

        //判断参数
        let xj: number, yj: number, distence: number, flag: number;
        let getXY: Function;

        //判断 //y=kx+b
        if (x1 == x2) { /*k不存在，也就是垂直的情况*/
            xj = x2;
            distence = y1 - y2;
            flag = compare(y1, y2);
            getXY = (i: number) => {
                return { x: xj, y: y1 + i + 5 * flag };
            };
        } else { /*斜率为正或者负或者0*/
            distence = x1 - x2;
            flag = compare(x1, x2);
            getXY = (i: number) => {
                xj = x1 + i + 5     //控制步长决定绘制的是虚线还是实线
                yj = k * xj + b;
                return { x: xj, y: yj };
            };
        }

        let i = 0;
        let draw = () => {
            let { x, y } = getXY(i);
            graphics.lineTo(x, y);
            graphics.stroke();
            i += step * flag;

            //判断退出
            if (Math.abs(i) > Math.abs(distence)) {
                this.isDrawing = false;
                this.unschedule(draw);
                //开始执行下一轮的绘制
                let nextDrawId = this.waitDrawList.pop();
                if (is.not.undefined(nextDrawId)) {
                    let nextDrawInfo = this.waitDrawMap.get(nextDrawId);
                    this.waitDrawMap.delete(nextDrawId);
                    this.drawLine(nextDrawInfo);
                }
            }
        }
        this.schedule(draw, drawInterval); //绘制
    }


    private checkIsDrawIng(drawInfo: I_LinePoint) {
        //正在绘制时返回
        if (this.isDrawing) {
            this.waitDrawMap.set(drawInfo.id, drawInfo);
            this.waitDrawList.push(drawInfo.id);
            return true;
        }
        this.isDrawing = true;
        return false;
    }
}

